L'agence "Santé publique France" a lancé un appel à projets pour rendre les données de santé plus accessibles. L’agence souhaite faire explorer et visualiser des données, pour que ses agents puissent les exploiter.
L'anayse est basée sur le jeu de données Open Food
Un environnement virtuel a été créé pour assurer l’isolement du projet et la gestion des dépendances. Les informations de cet environnement (son nom et ses dépendances) sont précisées dans le fichier environment.yml
L'installation de l'environnement virtuel est possible à partir de ce fichier, dans un invite de commande lancer la commande :
conda env create -f environment.yml
Le jeu de données contient : 320772 lignes et 162 colonnes
| code | url | creator | created_t | created_datetime | last_modified_t | last_modified_datetime | product_name | generic_name | quantity | ... | ph_100g | fruits-vegetables-nuts_100g | collagen-meat-protein-ratio_100g | cocoa_100g | chlorophyl_100g | carbon-footprint_100g | nutrition-score-fr_100g | nutrition-score-uk_100g | glycemic-index_100g | water-hardness_100g | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0000000003087 | http://world-fr.openfoodfacts.org/produit/0000... | openfoodfacts-contributors | 1474103866 | 2016-09-17T09:17:46Z | 1474103893 | 2016-09-17T09:18:13Z | Farine de blé noir | NaN | 1kg | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 0000000004530 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489069957 | 2017-03-09T14:32:37Z | 1489069957 | 2017-03-09T14:32:37Z | Banana Chips Sweetened (Whole) | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | 14.0 | 14.0 | NaN | NaN |
| 2 | 0000000004559 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489069957 | 2017-03-09T14:32:37Z | 1489069957 | 2017-03-09T14:32:37Z | Peanuts | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | 0.0 | 0.0 | NaN | NaN |
| 3 | 0000000016087 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055731 | 2017-03-09T10:35:31Z | 1489055731 | 2017-03-09T10:35:31Z | Organic Salted Nut Mix | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | 12.0 | 12.0 | NaN | NaN |
| 4 | 0000000016094 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055653 | 2017-03-09T10:34:13Z | 1489055653 | 2017-03-09T10:34:13Z | Organic Polenta | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 5 | 0000000016100 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055651 | 2017-03-09T10:34:11Z | 1489055651 | 2017-03-09T10:34:11Z | Breadshop Honey Gone Nuts Granola | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 6 | 0000000016117 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055730 | 2017-03-09T10:35:30Z | 1489055730 | 2017-03-09T10:35:30Z | Organic Long Grain White Rice | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7 | 0000000016124 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055711 | 2017-03-09T10:35:11Z | 1489055712 | 2017-03-09T10:35:12Z | Organic Muesli | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | 7.0 | 7.0 | NaN | NaN |
| 8 | 0000000016193 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055651 | 2017-03-09T10:34:11Z | 1489055651 | 2017-03-09T10:34:11Z | Organic Dark Chocolate Minis | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 9 | 0000000016513 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055654 | 2017-03-09T10:34:14Z | 1489055654 | 2017-03-09T10:34:14Z | Organic Sunflower Oil | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
10 rows × 162 columns
Affichage du nombre de valeurs manquantes en % pour chaque colonne
| Valeurs manquantes en % | |
|---|---|
| last_modified_t | 0.000000 |
| last_modified_datetime | 0.000000 |
| creator | 0.000623 |
| created_t | 0.000935 |
| created_datetime | 0.002806 |
| ... | ... |
| ingredients_that_may_be_from_palm_oil | 100.000000 |
| ingredients_from_palm_oil | 100.000000 |
| no_nutriments | 100.000000 |
| nervonic-acid_100g | 100.000000 |
| water-hardness_100g | 100.000000 |
162 rows × 1 columns
Affichage graphique du remplissage des colonnes
<AxesSubplot:>
Il y'a beaucoup de colonnes vides ou très peu remplies (plus de 75% de valeurs manquantes).
Avant de commencer l'analyse, il faut procéder à un nettoyage du jeu de données pour qu'il soit plus complet et plus uniforme.
On commence par supprimer les colonnes peu remplies, c'est à dire celles qui ont plus de 75% de valeurs manquantes
On supprime ensuite les lignes dont aucune donnée nutritionnelle n'a été renseignée (les colonnes terminant par _100g)
On supprime les lignes dont le code ou le nom du produit n'est pas renseigné
On vérifie si il y a des doublons pour le code des produits
| code | url | creator | created_t | created_datetime | last_modified_t | last_modified_datetime | product_name | quantity | brands | ... | fiber_100g | proteins_100g | salt_100g | sodium_100g | vitamin-a_100g | vitamin-c_100g | calcium_100g | iron_100g | nutrition-score-fr_100g | nutrition-score-uk_100g |
|---|
0 rows × 50 columns
Il n'y pas de doublon à déclarer.
On affiche donc les informations du data après le nettoyage :
Nombre de lignes supprimées : 61338 Nombre de colonnes supprimées : 112 Colonnes supprimées : ['generic_name', 'packaging', 'packaging_tags', 'origins', 'origins_tags', 'manufacturing_places', 'manufacturing_places_tags', 'labels', 'labels_tags', 'labels_fr', 'emb_codes', 'emb_codes_tags', 'first_packaging_code_geo', 'cities', 'cities_tags', 'purchase_places', 'stores', 'allergens', 'allergens_fr', 'traces', 'traces_tags', 'traces_fr', 'no_nutriments', 'ingredients_from_palm_oil', 'ingredients_from_palm_oil_tags', 'ingredients_that_may_be_from_palm_oil', 'ingredients_that_may_be_from_palm_oil_tags', 'nutrition_grade_uk', 'image_url', 'image_small_url', 'energy-from-fat_100g', 'butyric-acid_100g', 'caproic-acid_100g', 'caprylic-acid_100g', 'capric-acid_100g', 'lauric-acid_100g', 'myristic-acid_100g', 'palmitic-acid_100g', 'stearic-acid_100g', 'arachidic-acid_100g', 'behenic-acid_100g', 'lignoceric-acid_100g', 'cerotic-acid_100g', 'montanic-acid_100g', 'melissic-acid_100g', 'monounsaturated-fat_100g', 'polyunsaturated-fat_100g', 'omega-3-fat_100g', 'alpha-linolenic-acid_100g', 'eicosapentaenoic-acid_100g', 'docosahexaenoic-acid_100g', 'omega-6-fat_100g', 'linoleic-acid_100g', 'arachidonic-acid_100g', 'gamma-linolenic-acid_100g', 'dihomo-gamma-linolenic-acid_100g', 'omega-9-fat_100g', 'oleic-acid_100g', 'elaidic-acid_100g', 'gondoic-acid_100g', 'mead-acid_100g', 'erucic-acid_100g', 'nervonic-acid_100g', 'sucrose_100g', 'glucose_100g', 'fructose_100g', 'lactose_100g', 'maltose_100g', 'maltodextrins_100g', 'starch_100g', 'polyols_100g', 'casein_100g', 'serum-proteins_100g', 'nucleotides_100g', 'alcohol_100g', 'beta-carotene_100g', 'vitamin-d_100g', 'vitamin-e_100g', 'vitamin-k_100g', 'vitamin-b1_100g', 'vitamin-b2_100g', 'vitamin-pp_100g', 'vitamin-b6_100g', 'vitamin-b9_100g', 'folates_100g', 'vitamin-b12_100g', 'biotin_100g', 'pantothenic-acid_100g', 'silica_100g', 'bicarbonate_100g', 'potassium_100g', 'chloride_100g', 'phosphorus_100g', 'magnesium_100g', 'zinc_100g', 'copper_100g', 'manganese_100g', 'fluoride_100g', 'selenium_100g', 'chromium_100g', 'molybdenum_100g', 'iodine_100g', 'caffeine_100g', 'taurine_100g', 'ph_100g', 'fruits-vegetables-nuts_100g', 'collagen-meat-protein-ratio_100g', 'cocoa_100g', 'chlorophyl_100g', 'carbon-footprint_100g', 'glycemic-index_100g', 'water-hardness_100g'] Le jeu de données contient : 259434 lignes et 50 colonnes
Affichage graphique du remplissage des colonnes après le nettoyage
<AxesSubplot:>
| code | url | creator | created_t | created_datetime | last_modified_t | last_modified_datetime | product_name | quantity | brands | ... | fiber_100g | proteins_100g | salt_100g | sodium_100g | vitamin-a_100g | vitamin-c_100g | calcium_100g | iron_100g | nutrition-score-fr_100g | nutrition-score-uk_100g | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0000000004530 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489069957 | 2017-03-09T14:32:37Z | 1489069957 | 2017-03-09T14:32:37Z | Banana Chips Sweetened (Whole) | NaN | NaN | ... | 3.6 | 3.57 | 0.00000 | 0.000 | 0.000000 | 0.0214 | 0.000 | 0.00129 | 14.0 | 14.0 |
| 2 | 0000000004559 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489069957 | 2017-03-09T14:32:37Z | 1489069957 | 2017-03-09T14:32:37Z | Peanuts | NaN | Torn & Glasser | ... | 7.1 | 17.86 | 0.63500 | 0.250 | 0.000000 | 0.0000 | 0.071 | 0.00129 | 0.0 | 0.0 |
| 3 | 0000000016087 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055731 | 2017-03-09T10:35:31Z | 1489055731 | 2017-03-09T10:35:31Z | Organic Salted Nut Mix | NaN | Grizzlies | ... | 7.1 | 17.86 | 1.22428 | 0.482 | NaN | NaN | 0.143 | 0.00514 | 12.0 | 12.0 |
| 4 | 0000000016094 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055653 | 2017-03-09T10:34:13Z | 1489055653 | 2017-03-09T10:34:13Z | Organic Polenta | NaN | Bob's Red Mill | ... | 5.7 | 8.57 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 5 | 0000000016100 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055651 | 2017-03-09T10:34:11Z | 1489055651 | 2017-03-09T10:34:11Z | Breadshop Honey Gone Nuts Granola | NaN | Unfi | ... | 7.7 | 13.46 | NaN | NaN | NaN | NaN | 0.038 | 0.00346 | NaN | NaN |
| 6 | 0000000016117 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055730 | 2017-03-09T10:35:30Z | 1489055730 | 2017-03-09T10:35:30Z | Organic Long Grain White Rice | NaN | Lundberg | ... | NaN | 8.89 | NaN | NaN | NaN | 0.0027 | 0.044 | NaN | NaN | NaN |
| 7 | 0000000016124 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055711 | 2017-03-09T10:35:11Z | 1489055712 | 2017-03-09T10:35:12Z | Organic Muesli | NaN | Daddy's Muesli | ... | 9.4 | 14.06 | 0.13970 | 0.055 | NaN | NaN | 0.062 | 0.00422 | 7.0 | 7.0 |
| 8 | 0000000016193 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055651 | 2017-03-09T10:34:11Z | 1489055651 | 2017-03-09T10:34:11Z | Organic Dark Chocolate Minis | NaN | Equal Exchange | ... | 7.5 | 5.00 | NaN | NaN | NaN | NaN | 0.050 | 0.01125 | NaN | NaN |
| 9 | 0000000016513 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055654 | 2017-03-09T10:34:14Z | 1489055654 | 2017-03-09T10:34:14Z | Organic Sunflower Oil | NaN | Napa Valley Naturals | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 10 | 0000000016612 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055731 | 2017-03-09T10:35:31Z | 1489055731 | 2017-03-09T10:35:31Z | Organic Adzuki Beans | NaN | Unfi | ... | 12.5 | 22.92 | NaN | NaN | NaN | NaN | 0.062 | 0.00450 | NaN | NaN |
| 11 | 0000000016650 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055668 | 2017-03-09T10:34:28Z | 1489055668 | 2017-03-09T10:34:28Z | Organic Penne Pasta | NaN | Gardentime | ... | 1.8 | 14.04 | NaN | NaN | NaN | 0.0042 | NaN | 0.00126 | NaN | NaN |
| 12 | 0000000016872 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055650 | 2017-03-09T10:34:10Z | 1489055651 | 2017-03-09T10:34:11Z | Zen Party Mix | NaN | Sunridge | ... | 6.7 | 16.67 | 1.60782 | 0.633 | NaN | NaN | 0.133 | 0.00360 | 12.0 | 12.0 |
| 13 | 0000000016933 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055651 | 2017-03-09T10:34:11Z | 1489055651 | 2017-03-09T10:34:11Z | Organic Golden Flax Seeds | NaN | Unfi | ... | 38.1 | 19.05 | 0.09652 | 0.038 | NaN | NaN | 0.286 | 0.01286 | NaN | NaN |
| 14 | 0000000017497 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055678 | 2017-03-09T10:34:38Z | 1489055678 | 2017-03-09T10:34:38Z | Organic Spicy Punks | NaN | Eden | ... | 15.2 | 30.30 | 0.57658 | 0.227 | NaN | NaN | NaN | 0.00545 | NaN | NaN |
| 15 | 0000000018012 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055652 | 2017-03-09T10:34:12Z | 1489055653 | 2017-03-09T10:34:13Z | Cinnamon Nut Granola | NaN | Grizzlies | ... | 9.1 | 14.55 | 0.02286 | 0.009 | 0.000273 | NaN | NaN | 0.00131 | 0.0 | 0.0 |
| 16 | 0000000018050 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489050462 | 2017-03-09T09:07:42Z | 1489050462 | 2017-03-09T09:07:42Z | Organic Hazelnuts | NaN | Grizzlies | ... | 10.7 | 14.29 | 0.01016 | 0.004 | NaN | 0.0064 | 0.107 | 0.00450 | 0.0 | 0.0 |
| 17 | 0000000018173 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055667 | 2017-03-09T10:34:27Z | 1489055667 | 2017-03-09T10:34:27Z | Organic Sweetened Banana Chips | NaN | Unfi | ... | 3.3 | 3.33 | NaN | NaN | NaN | NaN | NaN | 0.00120 | NaN | NaN |
| 18 | 0000000018197 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055652 | 2017-03-09T10:34:12Z | 1489055652 | 2017-03-09T10:34:12Z | Lotus Organic Brown Jasmine Rice | NaN | Unfi | ... | 2.2 | 8.89 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 19 | 0000000018227 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055682 | 2017-03-09T10:34:42Z | 1489055682 | 2017-03-09T10:34:42Z | Organic Oat Groats | NaN | Pcc | ... | 9.5 | 16.67 | 0.02540 | 0.010 | NaN | NaN | 0.048 | 0.00429 | -6.0 | -6.0 |
| 20 | 0000000018265 | http://world-fr.openfoodfacts.org/produit/0000... | usda-ndb-import | 1489055706 | 2017-03-09T10:35:06Z | 1489055706 | 2017-03-09T10:35:06Z | Energy Power Mix | NaN | Sunridge | ... | 5.0 | 7.50 | 0.28448 | 0.112 | 0.000075 | 0.0225 | 0.100 | 0.00180 | 14.0 | 14.0 |
20 rows × 50 columns
Le jeu de données contient : 259434 lignes et 50 colonnes
Dans cette partie on va sélectionner les données intéressantes pour notre étude
On commence par catégoriser nos variables en 2 groupes : les variables qualitatives et quantitatives
Variables quantitatives: ['additives_n', 'ingredients_from_palm_oil_n', 'ingredients_that_may_be_from_palm_oil_n', 'energy_100g', 'fat_100g', 'saturated-fat_100g', 'trans-fat_100g', 'cholesterol_100g', 'carbohydrates_100g', 'sugars_100g', 'fiber_100g', 'proteins_100g', 'salt_100g', 'sodium_100g', 'vitamin-a_100g', 'vitamin-c_100g', 'calcium_100g', 'iron_100g', 'nutrition-score-fr_100g', 'nutrition-score-uk_100g'] Variables qualitatives: ['code', 'url', 'creator', 'created_t', 'created_datetime', 'last_modified_t', 'last_modified_datetime', 'product_name', 'quantity', 'brands', 'brands_tags', 'categories', 'categories_tags', 'categories_fr', 'countries', 'countries_tags', 'countries_fr', 'ingredients_text', 'serving_size', 'additives', 'additives_tags', 'additives_fr', 'nutrition_grade_fr', 'pnns_groups_1', 'pnns_groups_2', 'states', 'states_tags', 'states_fr', 'main_category', 'main_category_fr']
À partir de cette catégorisation, on ne va garder que les colonnes pertinentes dans le cas de notre étude :
Pour les variables qualitatives on sélectionne :
Pour les variables quantitatives on sélectionne :
Nombre de lignes supprimées : 0 Nombre de colonnes supprimées : 29 Colonnes supprimées : ['code', 'url', 'creator', 'created_t', 'created_datetime', 'last_modified_t', 'last_modified_datetime', 'quantity', 'brands', 'brands_tags', 'categories', 'categories_tags', 'categories_fr', 'countries', 'countries_tags', 'countries_fr', 'ingredients_text', 'serving_size', 'additives_n', 'additives', 'additives_tags', 'additives_fr', 'ingredients_from_palm_oil_n', 'ingredients_that_may_be_from_palm_oil_n', 'states', 'states_tags', 'states_fr', 'main_category_fr', 'nutrition-score-uk_100g'] Le jeu de données contient : 259434 lignes et 21 colonnes
On va maintenant analyser notre jeu de données sélectionné en s'intéressant principalement au nutrition_grade des produtis, ainsi qu'à leurs valeurs nuutritionnelles.
On effectue un second nettoyage un peu plus poussé sur les données qualitatives, afin d'uniformiser les données :
| product_name | nutrition_grade_fr | pnns_groups_1 | pnns_groups_2 | main_category | |
|---|---|---|---|---|---|
| 1 | banana chips sweetened (whole) | d | NaN | NaN | NaN |
| 2 | peanuts | b | NaN | NaN | NaN |
| 3 | organic salted nut mix | d | NaN | NaN | NaN |
| 4 | organic polenta | NaN | NaN | NaN | NaN |
| 5 | breadshop honey gone nuts granola | NaN | NaN | NaN | NaN |
product_name 183134 nutrition_grade_fr 5 pnns_groups_1 13 pnns_groups_2 36 main_category 2355 dtype: int64
On affiche les graphiques pour les colonnes ne présentant pas trop de valeurs uniques. On regroupe les valeurs représentant moins de 1.5% des données dans une catégorie nommée 'other'
Graphiques pour les données qualitatives
On voit que la répartition du nutri-score (noté de A à E) n'est pas uniforme, il y a une majorité de produits avec un mauvais nutriscore (C, D et E).
Les 19 catégories les plus courantes représentent environ 50% des produits.
Pour les différents groupes d'aliments (groupes 1 et 2), il y a une majorité de produits sucrés, laitiers ou céréales.
Ici on va afficher la répartition du nutrition_grade en fonction des autres variables qualitatives
On peut voir par exemple que les chocolats, biscuits, cakes, sugary snack ... ont généralement un mauvais nutri-score (D ou E), et que les canettes de nourriture, laits, céréales, fruits ... ont un bon nutri-score (A ou B)
On effectue un second nettoyage un peu plus poussé sur les données quantitatives, afin d'uniformiser les données :
| energy_100g | fat_100g | saturated-fat_100g | trans-fat_100g | cholesterol_100g | carbohydrates_100g | sugars_100g | fiber_100g | proteins_100g | salt_100g | sodium_100g | vitamin-a_100g | vitamin-c_100g | calcium_100g | iron_100g | nutrition-score-fr_100g | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 2.577730e+05 | 240584.000000 | 226641.000000 | 143159.000000 | 143950.000000 | 240276.000000 | 241910.000000 | 198587.000000 | 256605.000000 | 252527.000000 | 252488.000000 | 137398.000000 | 140655.00000 | 140837.000000 | 140305.000000 | 218463.000000 |
| mean | 1.140497e+03 | 12.701388 | 5.115709 | 0.073428 | 0.020079 | 32.091647 | 15.993129 | 2.863581 | 7.074330 | 2.037957 | 0.802467 | 0.000397 | 0.02335 | 0.125119 | 0.003654 | 9.151724 |
| std | 6.484434e+03 | 17.574028 | 8.008095 | 1.540612 | 0.358234 | 29.765368 | 22.345150 | 12.933636 | 8.418758 | 129.023620 | 50.800621 | 0.073320 | 2.23813 | 3.320757 | 0.214528 | 9.052588 |
| min | 0.000000e+00 | 0.000000 | 0.000000 | -3.570000 | 0.000000 | 0.000000 | -17.860000 | -6.700000 | -800.000000 | 0.000000 | 0.000000 | -0.000340 | -0.00210 | 0.000000 | -0.000260 | -15.000000 |
| 25% | 3.730000e+02 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 6.000000 | 1.300000 | 0.000000 | 0.700000 | 0.063500 | 0.025000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 1.000000 |
| 50% | 1.100000e+03 | 5.000000 | 1.790000 | 0.000000 | 0.000000 | 20.600000 | 5.710000 | 1.500000 | 4.760000 | 0.584200 | 0.230000 | 0.000000 | 0.00000 | 0.035000 | 0.001010 | 10.000000 |
| 75% | 1.674000e+03 | 20.000000 | 7.140000 | 0.000000 | 0.020000 | 58.500000 | 24.000000 | 3.600000 | 10.000000 | 1.379220 | 0.543000 | 0.000107 | 0.00370 | 0.106000 | 0.002400 | 16.000000 |
| max | 3.251373e+06 | 714.290000 | 550.000000 | 369.000000 | 95.238000 | 2916.670000 | 3520.000000 | 5380.000000 | 430.000000 | 64312.800000 | 25320.000000 | 26.700000 | 716.98110 | 694.737000 | 50.000000 | 40.000000 |
On voit que pour les données nutritionnelles (colonnes terminant par _100g) il y a des incohérences, il y a des valeurs négatives et des valeurs supérieures à 100 ce qui est impossible. Pour l'énergie et le nutrition-score exprimé en valeur numérique il y a également des abérrations, ici on utilisera la méthode de l'inter-quartile
On va donc supprimer les valeurs en dessous de 0 et au dessous de 100 pour les colonnes suivantes :
On va supprimer les outliers par la méthode de l'écart inter-quartiles, pour les colonnes suivantes :
| energy_100g | fat_100g | saturated-fat_100g | trans-fat_100g | cholesterol_100g | carbohydrates_100g | sugars_100g | fiber_100g | proteins_100g | salt_100g | sodium_100g | vitamin-a_100g | vitamin-c_100g | calcium_100g | iron_100g | nutrition-score-fr_100g | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 256709.000000 | 240580.000000 | 226638.000000 | 143150.000000 | 143950.000000 | 240258.00000 | 241892.000000 | 198582.000000 | 256601.000000 | 252371.000000 | 252454.000000 | 137397.000000 | 140651.000000 | 140827.000000 | 140304.000000 | 218459.000000 |
| mean | 1113.395627 | 12.696195 | 5.111649 | 0.067118 | 0.020079 | 32.07302 | 15.975216 | 2.833600 | 7.077845 | 1.593437 | 0.649009 | 0.000397 | 0.014532 | 0.101944 | 0.003654 | 9.151159 |
| std | 781.536587 | 17.497914 | 7.906154 | 0.944894 | 0.358234 | 29.16708 | 21.169760 | 4.591686 | 8.163246 | 6.261328 | 2.663027 | 0.073320 | 0.461745 | 0.585645 | 0.214529 | 9.051708 |
| min | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | -15.000000 |
| 25% | 372.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 6.00000 | 1.300000 | 0.000000 | 0.700000 | 0.063500 | 0.025000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 |
| 50% | 1093.000000 | 5.000000 | 1.790000 | 0.000000 | 0.000000 | 20.59000 | 5.710000 | 1.500000 | 4.760000 | 0.584200 | 0.230000 | 0.000000 | 0.000000 | 0.035000 | 0.001010 | 10.000000 |
| 75% | 1674.000000 | 20.000000 | 7.140000 | 0.000000 | 0.020000 | 58.45750 | 24.000000 | 3.600000 | 10.000000 | 1.374140 | 0.543000 | 0.000107 | 0.003700 | 0.106000 | 0.002400 | 16.000000 |
| max | 3619.000000 | 100.000000 | 100.000000 | 100.000000 | 95.238000 | 100.00000 | 100.000000 | 100.000000 | 100.000000 | 100.000000 | 100.000000 | 26.700000 | 100.000000 | 99.006000 | 50.000000 | 38.000000 |
Nos données quantitatives sont maintenant plus uniformes. Analysons comment les étudier :
Les données nutritionnelles principales sont :
Ces données principales servent à calculer :
Le calcul des calories d'un aliment s'effectue selon un processus normalisé au niveau européen et baptisé système « 4/4/9 » Ce système implique que l'équivalent calorique d'un gramme de protéines, de glucides et de lipides - nos trois principaux « carburants » nutritionnels - correspond respectivement à 4, 4 et 9 kcal.
1 gr de proteine apporte 4 kcal 1 gr de glucide (carbohydrate) apporte 4 kcal 1 gr de lipide apporte 9 kcal
On va rajouter 3 colonnes dans notre data :
| sum_nutritional_elements_100g | energy_calculated_100g | energy_difference | |
|---|---|---|---|
| count | 233195.000000 | 238411.000000 | 237191.000000 |
| mean | 53.390081 | 1130.291358 | 59.553247 |
| std | 33.897665 | 812.105339 | 146.763682 |
| min | 0.000000 | 0.000000 | 0.000000 |
| 25% | 20.636140 | 363.054770 | 7.644560 |
| 50% | 51.942180 | 1108.424510 | 22.745000 |
| 75% | 88.203350 | 1674.800000 | 57.127860 |
| max | 239.690000 | 6001.478320 | 4187.125610 |
Commencons par supprimer les produits dont la somme en g des valeurs nutritionnelles principales est supérieure à 100, car c'est impossible. Cela signifie que les données sont mal renseignées pour ce produit.
Affichons maintenant le graphique représentant pour les produits la différence entre l'énergie renseignée et celle calculée
On voit que pour la majorité des produits la différence d'énergie est très faible, ce qui signifie que notre calcul en utilisant les données nutritionnelles principales et le système 4/4/9 représente assez bien nos données. On choisit ici de supprimer les produits qui ont une différence supérieure à 300 kJ (correspondant à 72 kcal), cela signifie qu'il manque des données nutritionnelles ou qu'elles sont mal renseignées. Ceci nous permettra d'avoir des données plus pertinentes pour l'analyse
| energy_100g | fat_100g | saturated-fat_100g | trans-fat_100g | cholesterol_100g | carbohydrates_100g | sugars_100g | fiber_100g | proteins_100g | salt_100g | sodium_100g | vitamin-a_100g | vitamin-c_100g | calcium_100g | iron_100g | nutrition-score-fr_100g | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 222245.000000 | 222245.000000 | 198023.000000 | 135098.000000 | 135715.000000 | 222245.000000 | 212184.000000 | 171290.000000 | 222245.000000 | 222245.000000 | 222222.000000 | 129925.000000 | 132881.000000 | 132880.000000 | 132530.000000 | 192466.000000 |
| mean | 1094.718453 | 12.198456 | 4.859993 | 0.063144 | 0.020091 | 31.262919 | 15.713362 | 2.713325 | 6.957271 | 1.543991 | 0.607933 | 0.000363 | 0.011288 | 0.101180 | 0.003540 | 8.996976 |
| std | 776.236035 | 16.626035 | 7.244601 | 0.917228 | 0.327477 | 28.658474 | 20.713074 | 3.872652 | 7.875833 | 6.134678 | 2.415342 | 0.074111 | 0.299065 | 0.594034 | 0.214334 | 9.018269 |
| min | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | -14.000000 |
| 25% | 360.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 5.930000 | 1.500000 | 0.000000 | 0.700000 | 0.066040 | 0.026000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 |
| 50% | 1069.000000 | 4.900000 | 1.790000 | 0.000000 | 0.000000 | 20.000000 | 5.830000 | 1.600000 | 4.650000 | 0.600000 | 0.236220 | 0.000000 | 0.000000 | 0.035000 | 0.000960 | 9.000000 |
| 75% | 1644.000000 | 19.720000 | 7.140000 | 0.000000 | 0.022000 | 57.140000 | 23.500000 | 3.600000 | 10.000000 | 1.384300 | 0.545000 | 0.000107 | 0.003800 | 0.105000 | 0.002400 | 16.000000 |
| max | 3615.000000 | 100.000000 | 100.000000 | 100.000000 | 95.238000 | 100.000000 | 100.000000 | 100.000000 | 100.000000 | 100.000000 | 39.370079 | 26.700000 | 57.140000 | 99.006000 | 50.000000 | 37.000000 |
Affichage des informations sur le nouveau jeu de données Nombre de lignes supprimées : 37189 Nombre de colonnes supprimées : 0 Colonnes supprimées : [] Le jeu de données contient : 222245 lignes et 22 colonnes
On affiche les boîtes à moustaches ainsi que les histogrammes pour chaque variable quantitative
Si l'on se fie aux boîtes à moustaches on voit qu'il reste des outliers. Cela est du à la trop grandes répartition des valeurs autour de 0 pour certaines variables. Durant le nettoyage on a décidé de supprimer les valeurs en dessous de 0 et au dessus de 100 pour les données nutritionnelles, et de compléter le nettoyage en vérifiant le calcul de la somme des données nutritionnelles et le calcul de l'énergie.
La détermination des outliers avec la méthode de l'écart-interquartile n'est donc ici pas très pertinente, excepté pour l'énergie et le nutri-score mais les outliers ont été correctement supprimés lors du nettoyage.
On voit que les variables qui ont une distribution plus étalée correspondent à nos trois principaux « carburants » nutritionnels, protéine, glucide et le gras, ainsi que l'énergie et le nutriscore. Les autres variables étant des déclinaisons des principaux carburants sont moins souvent présente, d'ou leur plus grande répartion autour des petites valeurs.
Pour la suite de l'étude on va réduire les valeurs quantitatives sélectionnées. On ne va pas garder celles qui ont beaucoup trop de valeurs autour de 0. On ne va étudier que les variables ayant une répartion des valeurs assez importante pour pouvoir les comparer avec la variation d'énergie et le nutriscore.
Variables quantitatives sélectionnnées :
<class 'pandas.core.frame.DataFrame'> Int64Index: 222245 entries, 1 to 320768 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 product_name 222245 non-null object 1 nutrition_grade_fr 192467 non-null object 2 pnns_groups_1 47646 non-null object 3 pnns_groups_2 47729 non-null object 4 main_category 54524 non-null object 5 energy_100g 222245 non-null float64 6 fat_100g 222245 non-null float64 7 saturated-fat_100g 198023 non-null float64 8 carbohydrates_100g 222245 non-null float64 9 sugars_100g 212184 non-null float64 10 fiber_100g 171290 non-null float64 11 proteins_100g 222245 non-null float64 12 salt_100g 222245 non-null float64 13 sodium_100g 222222 non-null float64 14 nutrition-score-fr_100g 192466 non-null float64 dtypes: float64(10), object(5) memory usage: 27.1+ MB
Analysons maintenant les relations entre chaque variable quantitative
On remarque :
Regardons maintenant la matrice de corrélations
<AxesSubplot:>
Les indices de corrélation entre chaque variable quantitative nous permettent d'affirmer les remarques faites précedemment, à savoir :
Afon d'avoir un jeu de données plus complet pour pousser notre analyse, on va maintenant imputer les valeurs des données manquantes pour nos colonnes possédant encore un % de valeurs à Nan
| Valeurs manquantes en % | |
|---|---|
| product_name | 0.000000 |
| energy_100g | 0.000000 |
| fat_100g | 0.000000 |
| carbohydrates_100g | 0.000000 |
| proteins_100g | 0.000000 |
| salt_100g | 0.000000 |
| sodium_100g | 0.010349 |
| sugars_100g | 4.526986 |
| saturated-fat_100g | 10.898783 |
| nutrition_grade_fr | 13.398727 |
| nutrition-score-fr_100g | 13.399177 |
| fiber_100g | 22.927400 |
| main_category | 75.466715 |
| pnns_groups_2 | 78.524151 |
| pnns_groups_1 | 78.561497 |
<AxesSubplot:>
On voit que les colonnes suivantes ne sont pas encore complètes :
(On n'imputera pas les valeurs manquantes pour les variables qualitatives)
On va commencer par imputer les valeurs sur les données nutritionnelles par la médiane (et non par la moyenne car il y'a beaucoup d'outliers pour ces colonnes comme on a pu le voir avec les boîtes à moustaches)
Imputation des valeurs manquantes par la médiane pour les colonne suivantes : 'saturated-fat_100g', 'sugars_100g', 'fiber_100g'
<AxesSubplot:>
Maintenant que toutes les données nutritionelles sont complètes, on va imputer les valeurs manquantes de la colonne 'nutrition_grade_fr' (valeurs notées de A à E), en utilisant l'algorithme knn (Méthode des k plus proches voisins), ce qui permet d'imputer les valeurs d'un produit selon les produits qui lui ressemble le plus.
Cette colonne une fois complète nous permettra de déterminer les valeurs manquantes de la colonne 'nutrition-score-fr_100g', ces 2 colonnes étant étroitement corrélées. Pour ce faire, connaissant le nutrition-grade d'un produit, si son nutrition-score est manquant, on l'imputera avec la moyenne des nutrition-score dont le nutrition-grade est le même.
<AxesSubplot:>
Nos données quantitatives sont maintenant complètes, on va pouvoir aller un peu plus loin dans l'analyse des variables quantitatives.
On commencera par une analyse générale de notre jeu de données, pour voir si les remarques faites précedemment sont toujours valables après l'imputation des données manquantes, on vérifie que notre jeu de données à toujours "la même tendance". On fera ensuite une analyse descriptive du jeu de données.
<AxesSubplot:>
D'après l'analyse bivariée entre chaque variable quantitative et la matrice de corrélation, on remarque très peu de changement par rapport à la présente analyse faite avant l'imputation des données manquantes. L'imputation des données manquantes n'a donc pas modifié la tendance de notre de jeu de données, mais il est maintenant complet et permet une analyse plus poussée.
On va ici étudier la variabilité entre les individus, ainsi que les liaisons entre les variables.
Le nombre de composantes à analyser est de 4
l'ACP nous a permis de déterminer 4 composantes principales (F1 à F4), qui représentent les axes principaux d'inertie et totalisent à eux 86.4% de l'inertie du nuage de points des individus. Les axes d'inertie suivant sont trop peu représentatifs pour être intéressants à étudier.
La composante F1 est corrélée avec l'énergie, le nutrition_grade, le gras et le gras saturé. Si l'on se déplace sur la composante F1, on observe donc une augmentation de nutrition_grade en passant de A vers E, l'énergie du produit sera également plus importante. Comme vu précédemment, c'est bien le gras qui impacte le plus l'énergie du produit et son nutrition_grade. Les autres nutriments l'impactent aussi mais plus faiblement.
La composante F2 est corrélée avec le sel et le sodium. Si l'on se déplace sur la composante F2, les produits sont de plus en plus salés, et correspondent à un nutrition_grade de rang C ou D. Ils sont également de moins en moins gras et caloriques.
La composante F3 est corrélée positivement avec les glucides et le sucre, et négativement avec la protéine. Si l'on se déplace vers la droite sur la composante F3, les produits seront composés de plus de glucides et de moins de protéines sans impacter grandement l'énergie.
La composante F4 est corrélée à la fibre et aux protéines. Si l'on se déplace sur la composante F4, les produits seront composés de plus de fibres et de protéines, et le nutrition_grade sera impacté dans le sens inverse, les produits auront donc un meilleur rang, allant de E vers A.
Voici les hypothèses que l'on peut faire en fonction des différents rangs :
Étudions maintenant l'analyse de la variance entre chaque variable quantitative et le nutrition_grade
ANOVA entre chaque variable quantitative et la variable nutrition_grade
Avec ces boîtes à moustaches on observe la répartition des classes du nutrition_grade (A à E), pour chaque variable quantitative. On calcule ensuite le rapport de corrélation des variables (compris entre 0 et 1), qui est le rapport entre les variances interclasses et la variance totale. Il n'y a pas corrélation si les moyennes pas classes sont toutes égales ou presque. Il y a corrélation si les moyennes par classes sont très différentes.
On observe donc ici que les variables les plus corrélées avec le nutrition_grade sont :
Les glucides et le sucres le sont beaucoup moins :
Les autres nutriments ne sont pas corrélés avec le nutrition_grade
Cela correspond aux analyses précédentes et permet d'émettre les mêmes hypothèses
Cette analyse permet de mieux comprendre comment est calculé le nutri_score et le nutrition_grade.
Ce sont des indicateurs qui permettent de comparer les produits sur des critères nutritionnels, "A" correspondant à ceux de meilleure qualité nutritionnelle, et "E" au moins favorables.
D'après certaines recommentations, pour rester en bonne santé il convient d'avoir un apport journalier calorique à ne pas dépasser, et de varier les nutriments tout en favorisant les fibres, protéines, fruits et légumes ..., et limiter les produits très caloriques, les acides gras saturés, le sucre, le sel ...
Avec notre analyse on voit que les produits de meilleure qualité et meilleure pour la santé sont ceux à plus faible calorie et étant composés de fibres, ou de protéines. Vient ensuite les produits composés d'un peu de tout les nutriments, ou salés. Et les produits les moins bons sont les produits très sucrées ou très gras avec un très grand apport calorique.
Notre analyse correspond bien aux recommendations faites par l'agence nationale de sécurité sanitaire de l'alimentation, et nous permet de mieux comprendre l'impact des différents nutriments sur l'énergie d'un produit et son nutri_score.